<?php
/**
 * Représente une traduction d'un terme japonais
 * Plusieurs traductions peuvent avoir sur un terme précis
 *
 * @author Kévin Fauconnet (05/04/2013)
 */
 
class Translation extends SimpleModel {
	
	public $id_translation;
	public $id_term;
	public $category;
	public $title;
	public $translation;
	public $categories;
	
	public $last_update;
	public $last_update_id_user;
	public $last_update_comment;
	
	public $image;
	
	public $term;
	
	
	public function sqltable() { return "translations"; }
	
	public function schema() { return array(
		'id_translation' 		=> array('primarykey' => true, 'type' => 'int'),
		'id_term' 				=> 'int',
		'category'				=> 'string(128)',
		'title' 				=> 'string(128)',
		'translation'			=> 'string',
		'categories'			=> 'string',
		'last_update' 			=> 'datetime',
		'last_update_id_user'	=> 'int',
		'last_update_comment'	=> 'string',
		'image' 				=> 'string(128)'
	);}
	
	/**
	 * Crée un nouvel objet
	 */
	public function __construct($param = array()) {
		$this->id_translation = 0;
		$this->id_term = 0;
		$this->category = "";
		$this->title = "";
		$this->translation = "";
		$this->categories = array();
		$this->last_update = null;
		$this->last_update_id_user = null;
		$this->last_update_comment = null;
		
		$this->image = null;
		
		$this->term = null;
		
		$this->init($param);
	}
	
	/**
	 * Remplit l'objet depuis les résultats d'un PDOStatement
	 */
	public function fromStatement($rowFetched, $st) {
		parent::fromStatement($rowFetched);
		
		if (!empty($rowFetched['kana'])) {
			require_once(CLASS_PATH.'term.class.php');
			$t = new Term();
			$t->init($st);
			$this->term = $t;
		}
		
		if (!empty($this->categories)) {
			$this->categories = explode("\n", trim($this->categories));
		}
		else {
			$this->categories = array();
		}
	}
	
	/**
	 * Sauvegarde l'objet, et met à jour l'attribut last_update
	 */
	public function save($options = array()) {
		$this->last_update = date('d/m/Y H:i:s');
		$this->categories =  trim(implode("\n",$this->categories));
		
		$res = parent::save($options);
		$this->categories = explode("\n", $this->categories);
		return $res;
	}
	
	/**
	 * Récupère le term lié à une traduction
	 */
	public static function getTermTranslation($id_translation) {
		$sql = "SELECT terms.* FROM terms JOIN translations ON terms.id_term = translations.id_term";
		
		$where = array();
		$where[] = array('AND', 'id_translation = ?',$id_translation);
		
		$st = self::buildQuery(array(
			'query' => $sql,
			'where' => $where
		));
		
		$t = null;
		if ($st->fetch()) {
			require_once('term.class.php');
			$t = new Term($st);
		}
		return $t;
	}
	
	/**
	 * Récupère le term associé à la traduction
	 */
	public function getTerm($forced = false) {
		if (is_null($this->term) || $forced) {
			$this->term = self::getTermTranslation($this->id_translation);
		}
		return $this->term;
	}

	/**
	 * Construit la requête de traductions et l'exécute
	 *
	 * Options possible:
	 * - ids: uniquement un ensemble d'ids
	 * - withTerm: (boolean) permet de récupérer les données du Term associé (jointure)
	 *
	 * @param $options Array options
	 * @return PDOStatement le statement lié à la requête
	 */		
	public static function buildQueryTranslations($options = array()) {
		
		$sql = "SELECT * FROM translations";
		
		if (!empty($options['count'])) {
			$sql = "SELECT COUNT(*) FROM translations";
		}
		
		else if (!empty($options['withTerm'])) {
			$sql .= " LEFT JOIN terms ON translations.id_term = terms.id_term";
		}
		
		$where = array();
		
		if (!empty($options['ids'])) {
			$where[] = array('AND', 'id_translation IN ?', $options['ids']);
		}
		
		if (!empty($options['notids'])) {
			$where[] = array('AND', 'id_translation NOT IN ?', $options['notids']);
		}
		if (!empty($options['id_term'])) {
			$where[] = array('AND', 'id_term = ?', $options['id_term']);
		}
		if (!empty($options['term'])) {
			$term = '%'.$options['term'].'%';
			$where[] = array('AND', '(kana LIKE ? OR translation LIKE ? OR category LIKE ? OR categories LIKE ? OR pronunciation_romaji LIKE ?)', array_fill(0, 5, $term));
		}
		
		$queryOptions = array(
			'query' => $sql,
			'where' => $where
		);
		if (empty($options['count'])) {
			$queryOptions += array(
				'orderby' => 	self::getOption($options, 'orderby', 'title'),
				'limit' => 		self::getOption($options, 'limit'),
				'offset' => 	self::getOption($options, 'offset'),
				'page' => 		self::getOption($options, 'page')
			);
		}
		
		return self::buildQuery($queryOptions);
	}
	
	/**
	 * Renvoie le total de traductions
	 * Options possible:
	 * - ids: uniquement un ensemble d'ids
	 *
	 * @param $options Array options
	 * @return Array<int> liste d'id_translation
	 */		
	public static function countTranslations($options = array()) {
	
		$options['count'] = true;
		
		$st = self::buildQueryTranslations($options);
		$total = $st->fetchOne('int');
		return $total;
	}
	
	/**
	 * Renvoie une liste de traductions
	 * Options possible:
	 * - ids: uniquement un ensemble d'ids
	 * - withTerm: (boolean) permet de récupérer les données du Term associé (jointure)
	 * - orderby
	 * - limit
	 * - offset
	 * - page
	 *
	 * @param $options Array options
	 * @return Array<int> liste d'id_translation
	 */		
	public static function getTranslations($options = array()) {
		$st = self::buildQueryTranslations($options);
		
		$results = array();

		while ($st->fetch()) {
			$results[] = new self($st);
		}
		return $results;
	}
	
	/**
	 * Renvoie des ids de traductions
	 * Options possible:
	 * - notids: exclusions d'ids
	 *
	 * @param $options Array options
	 * @return Array<int> liste d'id_translation
	 */	
	public static function getIdsTranslations($options = array()) {
		
		$sql = "SELECT id_translation FROM translations";
		$where = array();
		
		if (!empty($options['notids'])) {
			$where[] = array('AND', 'id_translation NOT IN ?', $options['notids']);
		}
		
		$st = self::buildQuery(array(
			'query' => $sql,
			'where' => $where
		));
		
		$results = array();
		while ($row = $st->fetch()) {
			$results[] = $row['id_translation'];
		}
		
		return $results;
	}
	
	
	/**
	 * Renvoie des traductions aléatoires
	 * Options possible:
	 * - notids: exclusions d'ids, pour faire un aléatoire sur une série complète
	 * - max: nombre de traductions à renvoyer
	 *
	 * Les traductions sont renvoyés avec leur Term associé
	 *
	 * @param $options Array options
	 * @return Array<Translation> liste des traductions
	 */
	public static function getRandomTranslations($options = array()) {
		$notids = self::getOption($options, 'notids', array());
		$max = self::getOption($options, 'max', 10);
		$ids = array();
		
		$possible_ids = self::getIdsTranslations(array(
			'notids' => $notids
		));

		if (count($possible_ids) <= $max) {
			$ids = $possible_ids;
		}
		else {
			for ($i = 0; $i < $max; $i++) {
				$rand_index = mt_rand(0, count($possible_ids)-1);
				$ids[] = $possible_ids[$rand_index];
				array_splice($possible_ids,$rand_index, 1);
			}
		}

		$translations = self::getTranslations(array(
			'ids' => $ids,
			'withTerm' => true
		));
		return $translations;
	}
	
	/**
	 * Renvoie l'ensemble des catégories disponibles (avec ou sans mot clé)
	 */
	public static function getCategories($term = '') {
		$sql = "SELECT DISTINCT categories FROM translations";
		$where = array();
		
		if (!empty($term)) {
			$where[] = array('AND', 'categories LIKE ?', "%$term%");
		}
		
		$st = self::buildQuery(array(
			'query' => $sql,
			'where' => $where
		));
		$results = array();
		while ($row = $st->fetch()) {
			$categories = explode("\n", $row['categories']);
			foreach ($categories as $c) {
				$results[] = $c;
			}
		}
		
		$results = array_unique($results);
		if (!empty($term)) {
			$results_filtered = array();
			
			foreach ($results as $r) {
				if (stripos($r, $term) !== false) {
					$results_filtered[] = $r;
				}
			}
			$results = $results_filtered;
		}
		sort($results);
		return $results;
	}
	
	/**
	 * Indique si l'objet a eu des changements par rapport à sa version sauvegardé
	 */
	public function haveChanges() {
		$have_changes = true;
		if (!empty($this->id_translation)) {
			$have_changes = false;
			$o = new self($this->id_translation);
			$schema = $this->schema();
			
			// Test de tous les champs sauf last_update
			$attrs_exclude = array('last_update', 'last_update_id_user', 'last_update_comment');
			foreach ($schema as $attr => $opts) {
				if ($this->$attr != $o->$attr && !in_array($attr, $attrs_exclude)) {
					$have_changes = true;
					break;
				}
			}
		}
		return $have_changes;
	}

}
?>